package com.agile.leetcode.bitcanculate;

import org.junit.Test;

/**
 * 位运算法则
 * 0&0=0,0&1=0,1&1=1
 * 0|0=0,0|1=1,1|1=1
 * 0^0=0, 0^1=1, 1^1=0
 *
 * @Author KD
 * @Date 2021/1/27 11:26
 */
public class BitCalculate {
    /**
     * 7->1101
     * 1->0001
     * 偶数末尾是0
     * 奇数末尾是1
     * &运算则是 0&0=0,0&1=0,1&1=1
     * 测试是奇数还是偶数
     */
    @Test
    public void test() {
        int i = 7;
        if ((i & 1) == 1) {
            System.out.println(i + "是奇数");
        } else {
            System.out.println(i + "是偶数");
        }
    }

    /**
     * 交换两个数
     * 0^0=0, 0^1=1, 1^1=0
     * b=(a^b)^b=a^0=a
     * 0和任意数字进行异或操作结果为数字本身.
     * 两个相同的数字进行异或的结果为0
     */
    @Test
    public void test2() {
        int a = 8;
        int b = 10;
        a = a ^ b;
        b = a ^ b;
        a = a ^ b;
        System.out.println("a=" + a);
        System.out.println("b=" + b);
    }

    /**
     * 计算两个数的和
     * 位运算注意进位的问题
     *
     * @param a
     * @param b
     * @return
     */
    public static int test3(int a, int b) {
        int num1 = a ^ b;
        int num2 = a & b;
        num2 = num2 << 1;
        if (num2 == 0) {
            return num1;
        } else {
            return test3(num1, num2);
        }
    }

    /**
     * 给定一个非空整数数组，除了某个元素只出现一次以外，其余每个元素均出现两次。找出那个只出现了一次的元素。
     * 0和任意数字进行异或操作结果为数字本身.
     * 两个相同的数字进行异或的结果为0
     */
    @Test
    public void test4() {
        int[] arr = {1, 2, 3, 3, 3, 4, 4, 3, 2};
        int value = 0;
        for (int i : arr) {
            value ^= i;
        }
        System.out.println(value);
    }

    /**
     * 异或的结合律
     */
    @Test
    public void test5() {
        int a = 4;
        int b = 5;
        System.out.println((a ^ b) ^ b);
        System.out.println(a ^ (b ^ b));
    }

    /**
     * 利用位运算计算做大值
     */
    @Test
    public void test6() {
        long a = 98L;
        long b = 97L;
        // 左移63位得到符号位
        // a>b m=0 a<b m=-1
        long k = a - b;
        int m = (int) k >> 63;
        long reslut = (1 + m) * a - b * m;
        System.out.println(reslut);
    }

    /**
     * 计算二进制中1的个数
     */
    @Test
    public void test7() {
        // jdk提供计算二进制数中的1的个数
        int i = Integer.bitCount(9);
        // 转为二进制
        System.out.println(Integer.toBinaryString(9));
        System.out.println(i);
    }

    /**
     * 计算二进制数1的个数
     */
    @Test
    public void test8() {
        int result = 0;
        int n = 9;
        while (n != 0) {
            result += n & 1;
            // 1->0001 n->1001
            // n->无符号往右移->100
            n = n >>> 1;
            System.out.println(Integer.toBinaryString(n));
        }
        System.out.println(result);
    }

    @Test
    public void test9() {
        int i=5;
        System.out.println(Integer.toBinaryString(i));
        Integer j=new Integer(5);
        System.out.println(Integer.toBinaryString(j));
    }


    public static void main(String[] args) {
        System.out.println(test3(15, 15));
    }
}
